#lang racket
(require gregor
         simple-xlsx)

(define (plusdays d n)
  (define month '(31 28 31 30 31 30 31 31 30 31 30 31))
  (define (get-month-day y m)
    (cond
      [(= 2 m) (if (leap-year? y) 29 28)]
      [else (list-ref month (sub1 m))]))
  (define (plusdaysHelper y m d n)
    (cond
      ;; [(< n 0) (let ([absn (abs n)])
      ;;            (cond
      ;;              [(> (+ d n) 0) (date y m (+ d n))] ;;一个月之内
      ;;              [else (let ([newy (if (= m 1) (sub1 y) y)]
      ;;                          [newm (if (= m 1) 12 (sub1 m))])
      ;;                      (plusdaysHelper newy
      ;;                                      newm
      ;;                                      (get-month-day newy newm)
      ;;                                      (+ d n)
      ;;                                      ))]))]
      [(zero? n) (date y m d)] ;n=0
      [(<= (+ d n) (get-month-day y m)) (date y m (+ d n))] ;;month not change
      [else (plusdaysHelper (if (= 12 m) (add1 y) y)
                            (if (= 12 m) 1 (add1 m))
                            1
                            (- n (- (get-month-day y m) d) 1 ))]
      ))
  (let ([year (->year d)]
        [month (->month d)]
        [day (->day d)])
    (plusdaysHelper year month day n)))

;;yyyy/mm/dd -> <date>
(define (date-string->date str)
  (apply date
         (map string->number
              (string-split (string-replace str "/" " ")))))

;; (list string number) -> date
;;start date ,next n day -> the date of n day after start date
(define (nextnday input)
  (with-handlers ([exn? (λ (e) "null")])
    (plusdays (date-string->date (first input))
              (second input))))

(define (get-one-row rown xlsx)
  (for/list ([columns "ABC"])
    (get-cell-value (format "~a~a" columns rown ) xlsx)))

(define (->string d)
  (format "~a/~a/~a" (->year d) (->month d) (->day d)))

(define (result-parse re)
  (if (string? re)
      re
      (->string re)))

(module+ test
  (require rackunit)
  (with-input-from-xlsx-file
    "../cases/test.xlsx"
    (λ (xlsx)
      (let ([sheet1 (first  (get-sheet-names xlsx))])
        (load-sheet sheet1 xlsx)
        (let ([test-case-amount (car (get-sheet-dimension xlsx))])
          (for ([rows (range 1 (add1 test-case-amount))])
            (let* ([onecase (get-one-row rows xlsx)]
                   [result (result-parse (nextnday (take onecase 2)))])
              (check-equal? result (third onecase)
                            (format "第~a个用例,输入~a" rows onecase) )))
          )))))
